package com.xiyuan.smartutils;

import com.sun.org.apache.bcel.internal.generic.BasicType;
import com.xiyuan.smartutils.asm.ClassReader;
import com.xiyuan.smartutils.constants.TypeConstants;
import com.xiyuan.smartutils.control.Handler;
import com.xiyuan.smartutils.control.HandlerController;
import com.xiyuan.smartutils.filters.Filter;
import com.xiyuan.smartutils.filters.FilterEndsWith;
import com.xiyuan.smartutils.filters.JarFilter;
import com.xiyuan.smartutils.filters.PackageFilter;
import com.xiyuan.smartutils.function.SFunction;
import com.xiyuan.smartutils.reflect.Reflect;
import com.xiyuan.smartutils.reflect.Unsafe;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

/**
 * 类相关工具类
 *
 * @version v1.0.0 @author lgz 2017-9-21 新建与整理
 */

@SuppressWarnings("all")
public final class Classes implements TypeConstants {
    private static Classes INSTANCEE;
    
    private Classes() {
        Unsafe.init();
    }
    
    /*************************************************************/
    // 新建对象
    /*************************************************************/
    
    /**
     * 通过类名获取类结构 忽略异常
     *
     * @param className 类名
     * @return Class<?> 类结构
     */
    public static <T> Class<T> forName(String className) {
        try {
            return (Class<T>) forNameThrow(className, 0);
        }
        catch (Throwable e) {
            return null;
        }
    }
    
    /***
     * 通过类名获取类结构,如果有异常则返回null
     *
     * @param className 类名
     * @param policy 异常策略，小于0 忽略异常，1打印异常，2 抛异常
     * @return the class
     * @throws Exception 异常
     */
    public static Class<?> forNameThrow(String className, int policy) throws Exception {
        try {// 先在当前ClassLoader尝试,以保证不是系统默认的父ClassLoader优先
            return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
        }
        catch (Throwable e) {// ClassNotFoundException时再全局查一次
            try {
                return Class.forName(className);
            }
            catch (Throwable e1) {
                
                if (policy == 1) {
                    e1.printStackTrace();
                }
                
                if (policy >= 2) {
                    throw e1 instanceof Exception ? (Exception) e : new Exception(e);
                }
                
                return null;
            }
        }
    }
    
    /**
     * 获得对象数组的类数组
     *
     * @param objects 对象数组，如果数组中存在{@code null}元素，则此元素被认为是Object类型
     * @return 类数组
     */
    public static Class<?>[] getClasses(Object... objects) {
        Class<?>[] classes = new Class<?>[objects.length];
        Object obj;
        for (int i = 0; i < objects.length; i++) {
            obj = objects[i];
            if (null == obj) {
                classes[i] = Object.class;
            }
            else {
                classes[i] = obj.getClass();
            }
        }
        return classes;
    }
    
    /**
     * 获取指定类相同包名下的所有类结构
     *
     * @param clazz 指定类
     * @return 类结构
     * @throws IOException 异常
     */
    public static List<Class<?>> getClasses(Class<?> clazz) throws IOException {
        List<String> list = getClassNames(clazz);
        ArrayList<Class<?>> ls = new ArrayList<Class<?>>(list.size());
        for (String className : list) {
            Class<?> claz = forName(className.substring(0, className.lastIndexOf(".class")));
            if (claz != null) {
                ls.add(claz);
            }
        }
        
        ls.trimToSize();
        return ls;
    }
    
    /**
     * 获取指定类相同报名下的所有类全名列表
     *
     * @param clazz 指定类
     * @return 类结构列表
     * @throws IOException 异常
     */
    public static List<String> getClassNames(Class<?> clazz) throws IOException {
        if (clazz == null) {
            return new ArrayList<String>();
        }
        
        String packageName = clazz.getPackage().getName();
        List<String> ls = Resources.getResourceFileNameList(clazz, packageName.replaceAll("\\.", "/"));
        ArrayList<String> list = new ArrayList<String>(ls.size());
        for (String name : ls) {
            int j = name.lastIndexOf(".class");
            if (j == -1) {
                continue;
            }
            
            list.add(packageName + "." + name);
        }
        
        list.trimToSize();
        return list;
    }
    
    /**
     * 初始化实例，忽略异常，异常时返回null
     *
     * @param className 类名
     * @return 实例
     */
    public static Object newInstance(String className) {
        try {
            Class<?> cls = forName(className);
            return (cls == null) ? null : cls.newInstance();
        }
        catch (Throwable e) {
            return null;
        }
    }
    
    /**
     * 初始化实例，忽略异常，异常时返回null
     *
     * @param cls 类结构
     * @return 实例
     */
    public static <T> T newInstance(Class<T> cls) {
        try {
            return cls.newInstance();
        }
        catch (Throwable e) {
            return null;
        }
    }
    
    /**
     * 初始化数组，先创建数组对象，再转化为对象数组，基本类型转为对象类型，如int[]转为Integer[]
     *
     * @param cls    类结构
     * @param length 数组长度
     * @return 对象数组
     */
    public static Object[] newInstance(Class<?> cls, int length) {
        Object obj = Array.newInstance(cls, length);
        return Arrays.toArray(obj);
    }
    
    /**
     * 通过类结构和参数表组装成实例
     *
     * @param cls      类结构
     * @param paramMap 参数表
     * @return 组装成对象
     * @throws IllegalAccessException 非法访问异常
     */
    public static <T> T newInstance(Class<T> cls, Map<String, String> paramMap) throws IllegalAccessException {
        T obj = null;
        try {
            obj = cls.newInstance();
        }
        catch (Throwable e) {
            throw Asserts.exception("类[" + cls + "]无效或者不支持无参数实例化");
        }
        
        List<Field> fields = Classes.getFields(cls, true);
        for (Field field : fields) {
            String value = paramMap.get(field.getName());
            if (value == null) {// 前端没有参数的过滤
                continue;
            }
            
            Class<?> type = field.getType();
            if (!Types.isPrimitive(type) && !Types.isPrimitiveArray(type) && type != String.class && type != String[].class) {// 不支持的属性先过滤，仅支持8个基本类型和基本类型数组、字符串、字符串数组
                continue;
            }
            Reflect.setAccessible(field);
            switch (type.getName().hashCode()) {
                case BOOLEAN_CODE:
                    Reflect.set(obj,
                                field,
                                "true".equalsIgnoreCase(value) || "1".equals(value) || "Y".equalsIgnoreCase(value) || "YES".equalsIgnoreCase(
                                        value) || "ON".equalsIgnoreCase(value));
                    break;
                case BOOLEAN_CODE_OBJ: {
                    // 布尔型
                    Reflect.set(obj,
                                field,
                                value.isEmpty()
                                ? null
                                : "true".equalsIgnoreCase(value) || "1".equals(value) || "Y".equalsIgnoreCase(value) || "YES".equalsIgnoreCase(
                                        value) || "ON".equalsIgnoreCase(value));
                    break;
                }
                case BYTE_CODE:
                case BYTE_CODE_OBJ: {
                    // 字节型，支持去除0前缀
                    if (Validates.isInteger(value) || Validates.isNumeric(value)) {
                        Reflect.set(obj, field, Byte.parseByte(value));
                    }
                    break;
                }
                case CHAR_CODE:
                case CHAR_CODE_OBJ: {
                    // 字符型
                    if (value.length() == 1) {Reflect.set(obj, field, value.charAt(0));}
                    break;
                }
                case SHORT_CODE:
                case SHORT_CODE_OBJ: {
                    // 短整型，支持去除0前缀
                    if (Validates.isInteger(value) || Validates.isNumeric(value)) {
                        Reflect.set(obj, field, Short.parseShort(value));
                    }
                    break;
                }
                case INT_CODE:
                case INT_CODE_OBJ: {
                    // 整型，支持去除0前缀
                    if (Validates.isInteger(value) || Validates.isNumeric(value)) {
                        Reflect.set(obj, field, Integer.parseInt(value));
                    }
                    break;
                }
                case LONG_CODE:
                case LONG_CODE_OBJ: {
                    // 长整型，支持去除0前缀
                    if (Validates.isInteger(value) || Validates.isNumeric(value)) {
                        Reflect.set(obj, field, Long.parseLong(value));
                    }
                    break;
                }
                case FLOAT_CODE:
                case FLOAT_CODE_OBJ: {
                    // 浮点型
                    if (Validates.isFloat(value)) {Reflect.set(obj, field, Float.parseFloat(value));}
                    break;
                }
                case DOUBLE_CODE:
                case DOUBLE_CODE_OBJ: {
                    // 双字节浮点型
                    if (Validates.isFloat(value)) {Reflect.set(obj, field, Double.parseDouble(value));}
                    break;
                }
                case STRING_CODE: {
                    // 字符串
                    Reflect.set(obj, field, value);
                    break;
                }
                // 以下为数组
                case BOOLEAN_CODE_ARR: {
                    // 布尔型数组
                    boolean[] values = Arrays.toBooleanArrayForm(value, ",");
                    Reflect.set(obj, field, values);
                    break;
                }
                case BYTE_CODE_ARR: {
                    // 字节型数组，指定是UTF-8格式
                    if (!value.isEmpty()) {Reflect.set(obj, field, StrUtils.getBytesUTF8(value));}
                    break;
                }
                case CHAR_CODE_ARR: {
                    // 字符型数组
                    if (!value.isEmpty()) {Reflect.set(obj, field, value.toCharArray());}
                    break;
                }
                case SHORT_CODE_ARR: {
                    // 短整型数组
                    if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toShortArray(value));}
                    break;
                }
                case INT_CODE_ARR: {
                    // 整型数组
                    if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toIntArray(value));}
                    break;
                }
                case LONG_CODE_ARR: {
                    // 长整型数组
                    if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toLongArray(value));}
                    break;
                }
                case FLOAT_CODE_ARR: {
                    // 浮点型数组
                    if (Validates.isFloat(value)) {Reflect.set(obj, field, Arrays.toFloatArray(value));}
                    break;
                }
                case DOUBLE_CODE_ARR: {
                    // 双字节浮点型数组
                    if (Validates.isFloat(value)) {Reflect.set(obj, field, Arrays.toDoubleArray(value));}
                    break;
                }
                case STRING_CODE_ARR: {
                    // 字符串数组
                    Reflect.set(obj, field, Arrays.toStringArray(value));
                    break;
                }
            }
        }
        
        return obj;
    }
    
    /**
     * 通过类结构分析集合，得到一个集合对象，当前仅支持
     * 1.Collection.class,List.class,ArrayList.class返回ArrayList对象
     * 2.LinkedList.class返回LinkedList对象 3.Set.class,HashSet.class返回HashSet对象
     *
     * @param cls 类结构
     * @return 集合对象
     */
    public static Collection<Object> newList(Class<?> cls) {
        Collection<Object> list = null;
        if (cls == Collection.class || cls == List.class || cls == ArrayList.class) {
            return new ArrayList<Object>();
        }
        else if (cls == LinkedList.class) {
            return new LinkedList<Object>();
        }
        else if (cls == Set.class || cls == HashSet.class) {
            return new HashSet<Object>();
        }
        else {
            // 其他不支持，直接返回null;
            return list;
        }
    }
    
    /**
     * 通过类结构分析MAP，得到一个MAP对象，当前仅支持 1.Map.class,HashMap.class，返回HashMap对象
     * 2.ConcurrentMap.class,ConcurrentHashMap.class，返回ConcurrentHashMap对象
     * 3.Hashtable.class返回Hashtable对象 4.LinkedHashMap.class，返回LinkedHashMap对象
     * 5.TreeMap.class，返回TreeMap对象
     *
     * @param cls 类结构
     * @return MAP对象
     */
    public static <K, V> Map<K, V> newMap(Class<? extends Map> cls) {
        Map<K, V> map = null;
        if (cls == Map.class || cls == HashMap.class) {
            return new HashMap<K, V>(12);
        }
        else if (cls == ConcurrentMap.class || cls == ConcurrentHashMap.class) {
            return new ConcurrentHashMap<K, V>();
        }
        else if (cls == Hashtable.class) {
            return new Hashtable<K, V>();
        }
        else if (cls == LinkedHashMap.class) {
            return new LinkedHashMap<K, V>();
        }
        else if (cls == TreeMap.class) {
            return new TreeMap<K, V>();
        }
        else if (Map.class.isAssignableFrom(cls)) {
            return (Map<K, V>) newInstance(cls);
        }
        else {
            // 不支持的类型
            return map;
        }
    }
    
    /**
     * 通过类结构分析MAP，得到一个MAP对象，当前仅支持 1.MapSO.class,HashMapSO.class，返回HashMap对象
     * 2.LinkedMapSO.class，返回LinkedMapSO对象 3.TreeMapSO.class，返回TreeMapSO对象
     *
     * @param cls 类结构
     * @return MAP对象
     */
    public static Map<String, Object> newMapSO(Class<?> cls) {
        if (cls == Map.class || cls == HashMap.class) {
            return new HashMap<String, Object>();
        }
        else if (cls == ConcurrentMap.class || cls == ConcurrentHashMap.class) {
            return new ConcurrentHashMap<String, Object>();
        }
        else if (cls == Hashtable.class) {
            return new Hashtable<String, Object>();
        }
        else if (cls == LinkedHashMap.class) {
            return new LinkedHashMap<String, Object>();
        }
        else if (cls == TreeMap.class) {
            return new TreeMap<String, Object>();
        }
        else if (Map.class.isAssignableFrom(cls)) {
            return (Map<String, Object>) newInstance(cls);
        }
        else {
            // 不支持的类型
            return null;
        }
    }
    
    /**
     * 通过类结构分析MAP，得到一个MAP对象，当前仅支持 1.MapSS.class,HashMapSS.class，返回HashMap对象
     * 2.LinkedMapSS.class，返回LinkedMapSS对象 3.TreeMapSS.class，返回TreeMapSS对象
     *
     * @param cls 类结构
     * @return MAP对象
     */
    public static Map<String, String> newMapSS(Class<?> cls) {
        if (cls == Map.class || cls == HashMap.class) {
            return new HashMap<String, String>();
        }
        else if (cls == ConcurrentMap.class || cls == ConcurrentHashMap.class) {
            return new ConcurrentHashMap<String, String>();
        }
        else if (cls == Hashtable.class) {
            return new Hashtable<String, String>();
        }
        else if (cls == LinkedHashMap.class) {
            return new LinkedHashMap<String, String>();
        }
        else if (cls == TreeMap.class) {
            return new TreeMap<String, String>();
        }
        else if (Map.class.isAssignableFrom(cls)) {
            return (Map<String, String>) newInstance(cls);
        }
        else {
            // 不支持的类型
            return null;
        }
    }
    
    // /**
    // * 通过类结构和参数表组装成实例
    // *
    // * @param cls 类结构
    // * @param paramMap 参数表
    // * @return 组装成对象
    // * @throws IllegalAccessException 非法访问异常
    // */
    // public static <T> T newInstance(Class<T> cls, Map<String, String>
    // paramMap) throws IllegalAccessException {
    // T obj = null;
    // try {
    // obj = cls.newInstance();
    // }
    // catch (Throwable e) {
    // throw Asserts.exception("类[" + cls + "]无效或者不支持无参数实例化");
    // }
    //
    // List<Field> fields = Classes.getFieldListDeep(cls);
    // for (Field field : fields) {
    // String value = paramMap.get(field.getName());
    // if (value == null) {
    // // 前端没有参数的过滤
    // continue;
    // }
    //
    //
    // }
    //
    // return obj;
    // }
    //
    
    /**
     * 设置基础类型字段 值，如果是数组字段 value 则以逗号隔开
     *
     * @param field 字段名
     * @param obj   对象
     * @param value 值
     * @throws IllegalAccessException 异常信息
     */
    public static void setPrimitiveFieldValue(Field field, Object obj, String value) throws IllegalAccessException {
        Class<?> type = field.getType();
        if (!Types.isPrimitive(type) && !Types.isPrimitiveArray(type) && type != String.class && type != String[].class) {
            // 不支持的属性先过滤，仅支持8个基本类型和基本类型数组、字符串、字符串数组
            return;
        }
        
        Reflect.setAccessible(field);
        switch (type.getName().hashCode()) {
            case BOOLEAN_CODE:
            case BOOLEAN_CODE_OBJ: {
                // 布尔型
                Reflect.set(obj, field, "true".equalsIgnoreCase(value) || "1".equalsIgnoreCase(value));
                break;
            }
            case BYTE_CODE:
            case BYTE_CODE_OBJ: {
                // 字节型，支持去除0前缀
                if (Validates.isInteger(value) || Validates.isNumeric(value)) {
                    Reflect.set(obj, field, Byte.parseByte(value));
                }
                break;
            }
            case CHAR_CODE:
            case CHAR_CODE_OBJ: {
                // 字符型
                if (value.length() == 1) {Reflect.set(obj, field, value.charAt(0));}
                break;
            }
            case SHORT_CODE:
            case SHORT_CODE_OBJ: {
                // 短整型，支持去除 0 前缀
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Short.parseShort(value));}
                break;
            }
            case INT_CODE:
            case INT_CODE_OBJ: {
                // 整型，支持去除0前缀
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Integer.parseInt(value));}
                break;
            }
            case LONG_CODE:
            case LONG_CODE_OBJ: {
                // 长整型，支持去除0前缀
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Long.parseLong(value));}
                break;
            }
            case FLOAT_CODE:
            case FLOAT_CODE_OBJ: {
                // 浮点型
                if (Validates.isFloat(value)) {Reflect.set(obj, field, Float.parseFloat(value));}
                break;
            }
            case DOUBLE_CODE:
            case DOUBLE_CODE_OBJ: {
                // 双字节浮点型
                if (Validates.isFloat(value)) {Reflect.set(obj, field, Double.parseDouble(value));}
                break;
            }
            case STRING_CODE: {
                // 字符串
                Reflect.set(obj, field, value);
                break;
            }
            // 以下为数组
            case BOOLEAN_CODE_ARR: {
                // 布尔型数组
                boolean[] values = Arrays.toBooleanArrayForm(value, ",");
                Reflect.set(obj, field, values);
                break;
            }
            case BYTE_CODE_ARR: {
                // 字节型数组，指定是UTF-8格式
                if (value != null && !value.isEmpty()) {Reflect.set(obj, field, StrUtils.getBytesUTF8(value));}
                break;
            }
            case CHAR_CODE_ARR: {
                // 字符型数组
                if (value != null && !value.isEmpty()) {Reflect.set(obj, field, value.toCharArray());}
                break;
            }
            case SHORT_CODE_ARR: {
                // 短整型数组
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toShortArray(value));}
                break;
            }
            case INT_CODE_ARR: {
                // 整型数组
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toIntArray(value));}
                break;
            }
            case LONG_CODE_ARR: {
                // 长整型数组
                if (Validates.isInteger(value)) {Reflect.set(obj, field, Arrays.toLongArray(value));}
                break;
            }
            case FLOAT_CODE_ARR: {
                // 浮点型数组
                if (Validates.isFloat(value)) {Reflect.set(obj, field, Arrays.toFloatArray(value));}
                break;
            }
            case DOUBLE_CODE_ARR: {
                // 双字节浮点型数组
                if (Validates.isFloat(value)) {Reflect.set(obj, field, Arrays.toDoubleArray(value));}
                break;
            }
            case STRING_CODE_ARR: {
                // 字符串数组
                Reflect.set(obj, field, Arrays.toStringArray(value));
                break;
            }
            default:
                break;
        }
    }
    
    /*************************************************************/
    // 判断类结构相关
    /*************************************************************/
    
    /**
     * 判断类结构，是否继承自指定的类（含本类）
     *
     * @param cls        类结构
     * @param superClass 父类
     * @return =true表示继承现,=false表示未继承
     */
    public static boolean isExtends(Class<?> cls, Class<?> superClass) {
        return superClass == cls || superClass.isAssignableFrom(cls);
    }
    
    /**
     * 判断类结构，是否实现指定的接口（含本类）
     *
     * @param cls   类结构
     * @param iface 接口
     * @return =true表示实现,=false表示未实现
     */
    public static boolean isImplement(Class<?> cls, Class<?> iface) {
        if (iface == null || cls == null || cls == Object.class || Types.isPrimitiveBase(cls) || !iface.isInterface()) {
            return false;
        }
        return iface.isAssignableFrom(cls);
    }
    
    /**
     * 判断一个类是否是集合类
     *
     * @param clazz 类结构
     * @return =true表示真
     */
    public static boolean isCollection(Class<?> clazz) {
        return isImplement(clazz, Collection.class);
    }
    
    /**
     * 判断一个类是否是映射表类
     *
     * @param clazz 类结构
     * @return =true表示真
     */
    public static boolean isMap(Class<?> clazz) {
        return isImplement(clazz, Map.class);
    }
    
    /**
     * 判断是否是静态方法
     *
     * @param method 方法
     * @return =true表示是，=false表示不是
     */
    public static boolean isStaticMethod(Method method) {
        return (method.getModifiers() & Modifier.STATIC) != 0;
    }
    
    /**
     * 判断是否是静态属性
     *
     * @param field 属性
     * @return =true表示是，=false表示不是
     */
    public static boolean isStaticField(Field field) {
        return (field.getModifiers() & Modifier.STATIC) != 0;
    }
    
    /**
     * 判断是否是临时属性
     *
     * @param field 属性
     * @return =true表示是，=false表示不是
     */
    public static boolean isTransientField(Field field) {
        return (field.getModifiers() & Modifier.TRANSIENT) != 0;
    }
    
    /**
     * 判断是否是静态属性或临时属性
     *
     * @param field 属性
     * @return =true表示是，=false表示不是
     */
    public static boolean isStaticTransientField(Field field) {
        return (field.getModifiers() & Modifier.STATIC) != 0 || (field.getModifiers() & Modifier.TRANSIENT) != 0;
    }
    
    /**
     * 获取类中指定的方法，该方法仅支持查询本类定义的属性
     *
     * @param clazz 类结构
     * @param name  属性名称
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Method getMethod(Class<?> clazz, String name, Class<?>... parameterTypes) {
        try {
            return clazz.getDeclaredMethod(name, parameterTypes);
        }
        catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 获取类中指定的方法，支持深度查找，即如果没有则向上查询父类的属性
     *
     * @param clazz 类结构
     * @param name  属性名称
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Method getMethodDeep(Class<?> clazz, String name, Class<?>... parameterTypes) {
        Method method = getMethod(clazz, name, parameterTypes);
        while (method == null) {
            if (clazz == Object.class || clazz.getSuperclass() == Object.class) {
                break;
            }
            clazz = clazz.getSuperclass();
            method = getMethod(clazz, name, parameterTypes);
        }
        
        return method;
    }
    
    /**
     * 获取类中指定的属性，该方法仅支持查询本类定义的属性
     *
     * @param clazz 类结构
     * @param name  属性名称
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Field getField(Class<?> clazz, String name) {
        try {
            return clazz.getDeclaredField(name);
        }
        catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 获取类中指定的属性，支持深度查找，即如果没有则向上查询父类的属性
     *
     * @param clazz 类结构
     * @param name  属性名称
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Field getFieldDeep(Class<?> clazz, String name) {
        return getFieldDeep(clazz, name, 0);
    }
    
    /**
     * 获取类中指定的静态属性，支持深度查找，即如果没有则向上查询父类的属性
     *
     * @param cls  类结构
     * @param name 属性名称
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Field getFieldStaticDeep(Class<?> cls, String name) {
        return getFieldDeep(cls, name, 2);
    }
    
    /**
     * 获取类中指定的属性，支持深度查找，即如果没有则向上查询父类的属性
     *
     * @param clazz 类结构
     * @param name  属性名称
     * @param type  查询类型，0表示所有的属性，1表示仅实例属性，静态和临时的除外，2表示仅静态属性
     * @return 属性对应的结构 =null表示未查找，!=null表示查到
     */
    public static Field getFieldDeep(Class<?> clazz, String name, int type) {
        Asserts.as((type >= 0 && type <= 2) ? null : "查询属性类型，仅支持0,1,2请查看说明");
        Field field = null;
        do {
            field = getField(clazz, name);
            if (field != null) {
                if (type == 0) {return field;}
                else if (type == 1 && !isStaticTransientField(field)) {return field;}
                else if (type == 2 && isStaticField(field)) {return field;}
            }
            if (type != 1) {// 不是仅查实例属性，时优先查接口
                Class<?>[] classes = clazz.getInterfaces();
                for (Class<?> cls : classes) {
                    field = getFieldDeep(cls, name, type);
                    if (field != null) {return field;}
                }
            }
        }
        while (clazz != Object.class && (clazz = clazz.getSuperclass()) != Object.class);
        return field;
    }
    
    /**
     * 获取指定对象的字段值，异常抛unchecked异常
     *
     * @param obj   对象
     * @param field 对象字段名称
     * @return 返回字段值
     */
    public static Object getFieldValue(Object obj, String field) {
        Asserts.nonNull(field, "field");
        Field f = getField(obj.getClass(), field);
        
        return getFieldValue(obj, f);
    }
    
    /**
     * 获取指定对象的字段值，异常抛unchecked异常
     *
     * @param obj   对象
     * @param field 对象字段
     * @return 返回字段值
     */
    public static Object getFieldValue(Object obj, Field field) {
        try {
            Reflect.setAccessible(field);
            return Reflect.get(obj, field);
        }
        catch (Exception e) {
            throw Asserts.exception(e);
        }
    }
    
    /**
     * 设置指定对象的字段值，异常抛unchecked异常
     *
     * @param obj   对象
     * @param field 对象字段
     * @param value 值
     */
    public static void setFieldValue(Object obj, Field field, Object value) {
        setFieldValue(obj, field, value, false);
    }
    
    /**
     * 设置指定对象的字段值，异常抛unchecked异常
     *
     * @param obj   对象
     * @param field 对象字段
     * @param value 值
     */
    public static void setFieldValue(Object obj, Field field, Object value, boolean ignoreException) {
        try {
            Reflect.setAccessible(field);
            Reflect.set(obj, field, value);
        }
        catch (Exception e) {
            if (!ignoreException) {throw Asserts.exception(e);}
        }
    }
    
    /**
     * 获取类中指定的字段列表，支持深度查找父类的字段列表(父类的循递归查找),静态和临时两种属性不拷贝
     *
     * @param clazz 类
     * @return 返回字段列表，静态和临时除外
     */
    public static List<Field> getFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        getFields(clazz, fieldList, false);
        return fieldList;
    }
    
    /**
     * 获取类中指定的字段列表，支持深度查找父类的字段列表(父类的循递归查找),静态和临时两种属性不拷贝
     *
     * @param clazz 类
     * @return 返回字段列表，静态和临时除外
     */
    public static List<Field> getFields(Class<?> clazz, boolean deep) {
        List<Field> fieldList = new ArrayList<>();
        getFields(clazz, fieldList, deep);
        return fieldList;
    }
    
    /**
     * 获取类中指定的属性列表，支持深度查找父类的字段列表(父类的循递归查找),静态和临时两种属性不拷贝
     *
     * @param clazz     类
     * @param fieldList 用于存储的字段列表
     */
    private static void getFields(Class<?> clazz, List<Field> fieldList, boolean deep) {
        Field[] fieldArr = clazz.getDeclaredFields();
        for (Field field : fieldArr) {
            int mod = field.getModifiers();
            if (Modifier.isStatic(mod) || Modifier.isTransient(mod) || "this$0".equals(field.getName())) {
                continue;// 静态和临时两种属性不拷贝，内部类指向外部类的引用不拷贝
            }
            
            fieldList.add(field);
        }
        
        Class<?> superSrcClass = clazz.getSuperclass();
        if (superSrcClass != null && superSrcClass != Object.class) {
            getFields(superSrcClass, fieldList, deep);
        }
    }
    
    /**
     * 判断方法是否最后一个参数是数组参数
     *
     * @param method 方法
     * @return =true表示是，=false表示不是
     */
    public static boolean isMethodLastParamArray(Method method) {
        Class<?>[] paramTypes = method.getParameterTypes();
        return paramTypes.length > 0 && Types.isArray(paramTypes[paramTypes.length - 1]);
    }
    
    /**
     * 判断参数类型和和参数值是否匹配，要求个数相等，如果最后一个参数是数组的，请先组装好新的paramTypes
     *
     * @param paramTypes 参数数组类型
     * @param paramArray 参数数组对象
     * @return =true表示匹配成功
     */
    public static boolean isMethodParamMatch(Class<?>[] paramTypes, Object[] paramArray) {
        if (paramTypes.length != paramArray.length) {
            return false;
        }
        
        for (int i = 0; i < paramTypes.length; i++) {
            Class<?> clazz = paramTypes[i];
            Object param = paramArray[i];
            if (param == null) {
                // 参数为null时，要求不是基本类型
                if (Types.isPrimitive(clazz)) {
                    return false;
                }
            }
            else if (Types.isPrimitive(clazz)) {
                // 基本类型，数值型不一定匹配，要适配
                // long,int,short,byte
                // float,double
                // boolean
                // char
                
                if ((Types.isInteger(clazz) && !Types.isInteger(param)) || (Types.isDecimal(clazz) && !Types.isDecimal(
                        param)) || (Types.isBoolean(clazz) && !Types.isBoolean(param)) || (Types.isChar(clazz) && !Types.isChar(
                        param))) {
                    return false;
                }
                
            }
            else if (i == paramTypes.length - 1 && Types.isArray(clazz)) {
                // 最后一个数组支持实参不是数组，以便支持String...
                // params的形参，而实参是"abc"的情况
                if (clazz != param.getClass() && !clazz.getComponentType().isAssignableFrom(param.getClass())) {
                    return false;
                }
            }
            else {// 对象类型，判断是否其子类或本类
                if (clazz != param.getClass() && !clazz.isAssignableFrom(param.getClass())) {
                    return false;
                }
            }
        }
        
        return true;
    }
    
    /**
     * 比较判断types1和types2两组类，如果types1中所有的类都与types2对应位置的类相同，或者是其父类或接口，则返回{@code true}
     *
     * @param types1 类组1
     * @param types2 类组2
     * @return 是否相同、父类或接口
     */
    public static boolean isAllAssignableFrom(Class<?>[] types1, Class<?>[] types2) {
        if (types1 == types2 || (types1.length == 0 && types1.length == types2.length)) {
            return true;
        }
        if (null == types1 || null == types2) {
            // 任何一个为null不相等（之前已判断两个都为null的情况）
            return false;
        }
        if (types1.length != types2.length) {
            return false;
        }
        
        Class<?> type1;
        Class<?> type2;
        for (int i = 0; i < types1.length; i++) {
            type1 = types1[i];
            type2 = types2[i];
            if (Types.isPrimitive(type1) && Types.isPrimitive(type2)) {
                // 原始类型和包装类型存在不一致情况
                if (Types.getWrapType(type1) != Types.getWrapType(type2)) {
                    return false;
                }
            }
            else if (!type1.isAssignableFrom(type2)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 获取字段名
     *
     * @param fn  function
     * @param <T> the type of the input to the function
     * @param <R> the type of the result of the function
     * @return String
     */
    public static <T, R> String getFieldName(SFunction<T, R> fn) {
        return getFieldName(fn, "", 0);
    }
    
    /**
     * 获取字段名
     *
     * @param fn     function
     * @param split  大小写分割符
     * @param toType 0=不处理，1=转小写，2=转大写
     * @param <T>    the type of the input to the function
     * @param <R>    the type of the result of the function
     * @return String
     */
    public static <T, R> String getFieldName(SFunction<T, R> fn, String split, Integer toType) {
        
        String fieldName = LambdaUtils.getFieldName(fn);
        // 0.不做转换 1.大写 2.小写
        switch (toType) {
            case 1:
                return fieldName.replaceAll("[A-Z]", split + "$0").toUpperCase();
            case 2:
                return fieldName.replaceAll("[A-Z]", split + "$0").toLowerCase();
            default:
                return fieldName.replaceAll("[A-Z]", split + "$0");
        }
    }
    
    /**
     * 获取 指定类的所有子类，
     *
     * @param iface 父类或者接口
     * @param pkgs  筛选包名列表
     * @param <T>   接口类型
     * @return 子类列表
     */
    public static <T> List<Class<T>> getSubTypes(Class<T> iface, Collection<String> pkgs) {
        return getSubTypes(iface, null, pkgs, null);
    }
    
    /**
     * 获取 指定类的所有子类，
     *
     * @param iface 父类或者接口
     * @param pkg   筛选包名
     * @param pkgs  筛选包名列表
     * @param <T>   接口类型
     * @return 子类列表
     */
    public static <T> List<Class<T>> getSubTypes(Class<T> iface, String pkg, String... pkgs) {
        return getSubTypes(iface, null, pkg, pkgs);
    }
    
    /**
     * 获取 指定类的所有子类，
     *
     * @param iface 父类或者接口
     * @param pkgs  筛选包名列表
     * @param <T>   接口类型
     * @return 子类列表
     */
    public static <T> List<Class<T>> getSubTypes(Class<T> iface, Collection<String> pkgs, Collection<String> expkgs) {
        
        return getSubTypes(iface, null, pkgs, expkgs);
    }
    
    
    /**
     * 获取 指定类的所有子类，
     *
     * @param iface 父类或者接口
     * @param pkg   筛选包名
     * @param pkgs  筛选包名列表
     * @param <T>   接口类型
     * @return 子类列表
     */
    public static <T> List<Class<T>> getSubTypes(Class<T> iface, Filter<Class<?>> clzFilter, String pkg, String... pkgs) {
        Set<String> ls = new TreeSet<>();
        if (pkg != null) {ls.add(pkg);}
        if (pkgs != null) {ls.addAll(Arrays.asList(pkgs));}
        return getSubTypes(iface, clzFilter, ls, null);
    }
    
    
    /**
     * 获取 指定类的所有子类，
     *
     * <p>
     * 类筛选顺序 classPaths > pathFilter > excludePkgs > pkgs > clzFilter
     *
     * @param iface     父类或者接口
     * @param clzFilter 类路径过滤器
     * @param pkgs      筛选包名列表
     * @param excpkgs   排除筛选的包
     * @param <T>       接口类型
     * @return 子类列表
     */
    public static <T> List<Class<T>> getSubTypes(Class<T> iface, Filter<Class<?>> clzFilter, Collection<String> pkgs, Collection<String> excpkgs) {
        if (iface == null) {return new ArrayList<Class<T>>(0);}
        if (clzFilter == null) {clzFilter = r -> iface != r && iface.isAssignableFrom(r);}
        Filter<Class<?>> ff = clzFilter;
        return scans(pkgs,
                     excpkgs,
                     (r) -> iface.isAssignableFrom(r)
                             && !r.getName().equals(iface.getName())
                             && ff.accept(r))
                .stream()
                .map(r -> (Class<T>) r)
                .collect(Collectors.toList());
        
        
    }
    
    /**
     * 扫描指定类路径，根据提供的过滤器和处理器处理
     *
     * @param pkg  扫描那些包
     * @param pkgs 扫描那些包
     * @return 类名列表
     */
    public static List<Class<?>> scans(String pkg, String... pkgs) {
        return scans(null, pkg, pkgs);
    }
    
    /**
     * 扫描指定类路径，根据提供的过滤器和处理器处理
     * <p>
     * 类筛选顺序 classPaths > pathFilter > excludePkgs > pkgs > clzFilter
     *
     * @param clzFilter 类路径过滤器
     * @param pkg       扫描那些包
     * @param pkgs      扫描那些包
     * @return 类名列表
     */
    public static List<Class<?>> scans(Filter<Class<?>> clzFilter, String pkg, String... pkgs) {
        Collection<String> packages = new LinkedHashSet<>();
        if (pkg != null) {packages.add(pkg);}
        if (pkgs != null && pkgs.length > 0) {packages.addAll(Arrays.asList(pkgs));}
        return scans(packages, null, clzFilter);
    }
    
    
    /**
     * 指定package 扫描所有类
     * <p>
     * 类筛选顺序 classPaths > pathFilter > excludePkgs > pkgs > clzFilter
     *
     * @param clzFilter 类路径过滤器
     * @param pkgs      扫描包名
     * @param exPkgs    排除包名
     * @return List 类名列表
     */
    public static List<Class<?>> scans(Collection<String> pkgs, Collection<String> exPkgs, Filter<Class<?>> clzFilter) {
        
        ClassLoader tl = Thread.currentThread().getContextClassLoader();
        if (tl == null) {tl = ClassLoader.getSystemClassLoader();}
        
        
        final ClassLoader loader = tl;
        // final URLClassLoader loader = tl;
        final Filter<String> classFileFilter = new FilterEndsWith(".class", true);
        final PackageFilter pkgFilter = new PackageFilter(pkgs, exPkgs);
        final Set<String> names = new ConcurrentSkipListSet<String>();
        final Set<Class<?>> classes = new ConcurrentSkipListSet<Class<?>>(Comparator.comparing(Class::getName));
        final AtomicInteger total = new AtomicInteger();
        final AtomicInteger currt = new AtomicInteger();
        
        
        Classes.initThreadPool();// 初始化
        final Handler<String> classHandler = cname -> {
            total.incrementAndGet();
            // 这里使用多线程处理
            TC.execute(() -> {
                try {
                    String className = cname.replaceAll("/", ".");
                    if (!names.contains(className)) {
                        Class<?> cla = loader.loadClass(className);// loader.from(className, kv.value());
                        if (cla != null && (clzFilter == null || (clzFilter.accept(cla)))) {
                            classes.add(cla);
                            names.add(className);
                        }
                    }
                }
                catch (Throwable e) {}
                finally {
                    // 最后进行比较
                    currt.incrementAndGet();
                }
            });
        };
        
        final JarFilter jarFileFilter = new JarFilter() {
            @Override
            public boolean accept(JarEntry src) {
                String name = src.getName();
                return classFileFilter.accept(name) || Jars.isJarFile(name);
            }
            
            @Override
            public void process(JarFile jarFile, JarEntry jarEntry) {
                try {
                    String name = jarEntry.getName();
                    int idx = name.lastIndexOf('/');
                    String pkg = idx == -1 ? "" : name.substring(0, idx);
                    // class 文件 并且 在扫描包里面 才能被加载
                    if (classFileFilter.accept(name) && pkgFilter.accept(pkg)) {
                        // 直接通过 entryName 当做 包名过滤 可以减少 读取文件次数 提升性能
                        String className = jarEntry.getName().substring(0, jarEntry.getName().length() - 6);
                        classHandler.process(className);
                    }
                    else {
                        // TODO jarEntry 是个jar包
                    }
                }
                catch (Throwable e) {}
            }
        };
        
        final String javaHome = "/" + StrUtils.trimRight(StrUtils.trimRight(Systems.getJavaHome(), "/"), "/jre");
        final String jLib1 = javaHome + "/lib";
        final String jLib2 = javaHome + "/jre/lib";
        
        final String jBin1 = javaHome + "/bin";
        final String jBin2 = javaHome + "/jre/bin";
        // 线执行
        Filter<URL> pathFilter = src -> {
            String urlFile = src.getFile();
            // 保留 ${javaHome}/ bin 目录
            if (urlFile.indexOf(jBin1) == 0 || urlFile.indexOf(jBin2) == 0) return false;
            
            // 忽略 lib 目录
            if (urlFile.indexOf(jLib1) == 0 || urlFile.indexOf(jLib2) == 0) return false;
            
            // 忽略 javaHome 目录
            return urlFile.indexOf(javaHome) != 0;
        };
        
        Set<URL> jar2jar = new LinkedHashSet<>();
        Set<File> urlClzs = new LinkedHashSet<>();
        Set<File> localFiles = new LinkedHashSet<>();
        
        Set<ClassLoader> loaders = new LinkedHashSet<>();
        ClassLoader loader1 = loader;
        while (loader1 != null) {
            loaders.add(loader1);
            loader1 = loader1.getParent();
            if (loaders.contains(loader1) || loader1 == null) break;
        }
        
        Set<String> urls = new LinkedHashSet<>();
        
        Handler<URL[]> loader_handler = new Handler<URL[]>() {
            @Override
            public void process(URL[] urls1) {
                for (URL r : urls1) {
                    String path = r.toExternalForm();
                    if (urls.contains(path)) {
                        continue;
                    }
                    urls.add(path);
                    
                    try {
                        // 类路径被过滤
                        if (!pathFilter.accept(r)) continue;
                        
                        if ("jar".equals(r.getProtocol())) {
                            jar2jar.add(r);
                            continue;
                        }
                        
                        if (!"file".equals(r.getProtocol())) {continue;}
                        
                        File file = new File(r.toURI());
                        if (!Files.exists(file) || !file.canRead()) {continue;}
                        
                        Files.forEach(file, file1 -> {
                            try {
                                if (classFileFilter.accept(file1.getName())) {
                                    urlClzs.add(file1);
                                }
                                else if (Jars.isJarFile(file1)) {
                                    localFiles.add(file1);
                                }
                            }
                            catch (Exception e) {
                            
                            }
                        });
                    }
                    catch (Exception e) {}
                }
            }
        };
        
        loaders.forEach(_loader -> loader_handler.process(getURLs(_loader)));
        
        // 有限本地jar
        for (File file : localFiles) Jars.filter(file, jarFileFilter);
        
        // 加载 本地 classes
        for (File url : urlClzs) {
            File file = new File(url.toURI());
            byte[] bytes = Files.read(file);
            ClassReader reader = new ClassReader(bytes);
            String className = reader.getClassName();
            int idx = className.lastIndexOf('/');
            String pkg = idx == -1 ? "" : className.substring(0, idx);
            if (pkgFilter.accept(pkg)) classHandler.process(className);
        }
        
        // 扫描jar 中 jar, 例如：spring boot 路径
        for (URL url : jar2jar) {
            try {
                Object obj = url.getContent();
                if (obj == null) ;
                if (obj instanceof JarFile) {
                    Jars.filter((JarFile) obj, jarFileFilter);
                }
            }
            catch (Exception e) {}
        }
        
        // 因为是边扫描边处理，所以 这里只能 通过 while 监听
        int tm = 0;
        while (total.get() != currt.get()) {
            // 如果队列为空，计次 +1
            if (TC.isEmpty()) tm++;
            // 如果 队列长时间为空并且（50毫秒*1000次相当50秒钟）没有数据则直接退出，
            if (tm > 1000) break;
            Threads.sleepIgnoreException(50);
        }
        
        return new ArrayList<>(classes);
    }
    
    private static final HandlerController TC = new HandlerController();
    static Method getPackages = null;
    
    public static Package[] getPackages(ClassLoader loader) {
        try {
            if (getPackages == null) {
                getPackages = ClassLoader.class.getDeclaredMethod("getPackages");
                getPackages.setAccessible(true);
            }
            return (Package[]) getPackages.invoke(loader);
        }
        catch (Exception e) {
            return Package.getPackages();
        }
    }
    
    private static HandlerController initThreadPool() {
        
        if (TC != null && !TC.isRunning()) {
            TC.setDaemon(true);
            TC.init(0, 1, 1, 999999999);
            TC.start();
        }
        
        return TC;
    }
    
    private static Object getUcp(Class<?> loaderClass, ClassLoader obj) {
        if (ClassLoader.class.isAssignableFrom(loaderClass)) {
            try {
                Field ucpField = loaderClass.getDeclaredField("ucp");
                if (!ucpField.isAccessible()) {
                    Unsafe.setAccessible(ucpField, true);
                }
                return ucpField.get(obj);
            }
            catch (Throwable e) {
                return getUcp(loaderClass.getSuperclass(), obj);
            }
        }
        return null;
    }
    
    private static URL[] getURLs(ClassLoader loader) {
        Class loader_class = loader.getClass();
        String loader_name = loader_class.getName();
        if (Systems.JAVA_MAIN_VERSION >= 9 && loader_name.startsWith("jdk.internal.loader.")) {
            try {
                
                Object ucp = getUcp(loader_class, loader);
                Field pathField = ucp.getClass().getDeclaredField("path");
                if (!pathField.isAccessible()) {
                    Unsafe.setAccessible(pathField, true);
                }
                
                List<URL> paths = (List<URL>) pathField.get(ucp);
                return paths == null ? new URL[0] : paths.toArray(new URL[0]);
            }
            catch (Throwable e) {
                System.out.println();
                return new URL[0];
            }
        }
        
        if (loader instanceof URLClassLoader) {
            return ((URLClassLoader) loader).getURLs();
        }
        
        // TODO 这里后续在完善 其他类的加载方式
        return new URL[0];
    }
    
    static {
        INSTANCEE = new Classes();
        initThreadPool();
        
    }
}